home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / FromTheMag / XAMPP 1.4.14 / xampp-win32-1.4.14-installer.exe / xampp / php / pear / XML / Util.php < prev    next >
PHP Script  |  2004-10-01  |  24KB  |  654 lines

  1. <?PHP
  2. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2002 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.0 of the PHP license,       |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available at through the world-wide-web at                           |
  11. // | http://www.php.net/license/2_02.txt.                                 |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Stephan Schmidt <schst@php-tools.net>                       |
  17. // +----------------------------------------------------------------------+
  18. //
  19. //    $Id: Util.php,v 1.20 2004/06/27 18:15:13 schst Exp $
  20.  
  21. /**
  22.  * error code for invalid chars in XML name
  23.  */
  24. define("XML_UTIL_ERROR_INVALID_CHARS", 51);
  25.  
  26. /**
  27.  * error code for invalid chars in XML name
  28.  */
  29. define("XML_UTIL_ERROR_INVALID_START", 52);
  30.  
  31. /**
  32.  * error code for non-scalar tag content
  33.  */
  34. define("XML_UTIL_ERROR_NON_SCALAR_CONTENT", 60);
  35.     
  36. /**
  37.  * error code for missing tag name
  38.  */
  39. define("XML_UTIL_ERROR_NO_TAG_NAME", 61);
  40.     
  41. /**
  42.  * replace XML entities
  43.  */
  44. define("XML_UTIL_REPLACE_ENTITIES", 1);
  45.  
  46. /**
  47.  * embedd content in a CData Section
  48.  */
  49. define("XML_UTIL_CDATA_SECTION", 2);
  50.  
  51. /**
  52.  * do not replace entitites
  53.  */
  54. define("XML_UTIL_ENTITIES_NONE", 0);
  55.  
  56. /**
  57.  * replace all XML entitites
  58.  * This setting will replace <, >, ", ' and &
  59.  */
  60. define("XML_UTIL_ENTITIES_XML", 1);
  61.  
  62. /**
  63.  * replace only required XML entitites
  64.  * This setting will replace <, " and &
  65.  */
  66. define("XML_UTIL_ENTITIES_XML_REQUIRED", 2);
  67.  
  68. /**
  69.  * replace HTML entitites
  70.  * @link    http://www.php.net/htmlentities
  71.  */
  72. define("XML_UTIL_ENTITIES_HTML", 3);
  73.  
  74. /**
  75.  * utility class for working with XML documents
  76.  *
  77.  * @category XML
  78.  * @package  XML_Util
  79.  * @version  0.6.0
  80.  * @author   Stephan Schmidt <schst@php.net>
  81.  */
  82. class XML_Util {
  83.  
  84.    /**
  85.     * return API version
  86.     *
  87.     * @access   public
  88.     * @static
  89.     * @return   string  $version API version
  90.     */
  91.     function apiVersion()
  92.     {
  93.         return "0.6";
  94.     }
  95.  
  96.    /**
  97.     * replace XML entities
  98.     *
  99.     * With the optional second parameter, you may select, which
  100.     * entities should be replaced.
  101.     *
  102.     * <code>
  103.     * require_once 'XML/Util.php';
  104.     * 
  105.     * // replace XML entites:
  106.     * $string = XML_Util::replaceEntities("This string contains < & >.");
  107.     * </code>
  108.     *
  109.     * @access   public
  110.     * @static
  111.     * @param    string  string where XML special chars should be replaced
  112.     * @param    integer setting for entities in attribute values (one of XML_UTIL_ENTITIES_XML, XML_UTIL_ENTITIES_XML_REQUIRED, XML_UTIL_ENTITIES_HTML)
  113.     * @return   string  string with replaced chars
  114.     */
  115.     function replaceEntities($string, $replaceEntities = XML_UTIL_ENTITIES_XML)
  116.     {
  117.         switch ($replaceEntities) {
  118.             case XML_UTIL_ENTITIES_XML:
  119.                 return strtr($string,array(
  120.                                           '&'  => '&',
  121.                                           '>'  => '>',
  122.                                           '<'  => '<',
  123.                                           '"'  => '"',
  124.                                           '\'' => ''' ));
  125.                 break;
  126.             case XML_UTIL_ENTITIES_XML_REQUIRED:
  127.                 return strtr($string,array(
  128.                                           '&'  => '&',
  129.                                           '<'  => '<',
  130.                                           '"'  => '"' ));
  131.                 break;
  132.             case XML_UTIL_ENTITIES_HTML:
  133.                 return htmlspecialchars($string);
  134.                 break;
  135.         }
  136.         return $string;
  137.     }
  138.  
  139.    /**
  140.     * build an xml declaration
  141.     *
  142.     * <code>
  143.     * require_once 'XML/Util.php';
  144.     * 
  145.     * // get an XML declaration:
  146.     * $xmlDecl = XML_Util::getXMLDeclaration("1.0", "UTF-8", true);
  147.     * </code>
  148.     *
  149.     * @access   public
  150.     * @static
  151.     * @param    string  $version     xml version
  152.     * @param    string  $encoding    character encoding
  153.     * @param    boolean $standAlone  document is standalone (or not)
  154.     * @return   string  $decl xml declaration
  155.     * @uses     XML_Util::attributesToString() to serialize the attributes of the XML declaration
  156.     */
  157.     function getXMLDeclaration($version = "1.0", $encoding = null, $standalone = null)
  158.     {
  159.         $attributes = array(
  160.                             "version" => $version,
  161.                            );
  162.         // add encoding
  163.         if ($encoding !== null) {
  164.             $attributes["encoding"] = $encoding;
  165.         }
  166.         // add standalone, if specified
  167.         if ($standalone !== null) {
  168.             $attributes["standalone"] = $standalone ? "yes" : "no";
  169.         }
  170.         
  171.         return sprintf("<?xml%s?>", XML_Util::attributesToString($attributes, false));
  172.     }
  173.  
  174.    /**
  175.     * build a document type declaration
  176.     *
  177.     * <code>
  178.     * require_once 'XML/Util.php';
  179.     * 
  180.     * // get a doctype declaration:
  181.     * $xmlDecl = XML_Util::getDocTypeDeclaration("rootTag","myDocType.dtd");
  182.     * </code>
  183.     *
  184.     * @access   public
  185.     * @static
  186.     * @param    string  $root         name of the root tag
  187.     * @param    string  $uri          uri of the doctype definition (or array with uri and public id)
  188.     * @param    string  $internalDtd  internal dtd entries   
  189.     * @return   string  $decl         doctype declaration
  190.     * @since    0.2
  191.     */
  192.     function getDocTypeDeclaration($root, $uri = null, $internalDtd = null)
  193.     {
  194.         if (is_array($uri)) {
  195.             $ref = sprintf( ' PUBLIC "%s" "%s"', $uri["id"], $uri["uri"] );
  196.         } elseif (!empty($uri)) {
  197.             $ref = sprintf( ' SYSTEM "%s"', $uri );
  198.         } else {
  199.             $ref = "";
  200.         }
  201.  
  202.         if (empty($internalDtd)) {
  203.             return sprintf("<!DOCTYPE %s%s>", $root, $ref);
  204.         } else {
  205.             return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
  206.         }
  207.     }
  208.  
  209.    /**
  210.     * create string representation of an attribute list
  211.     *
  212.     * <code>
  213.     * require_once 'XML/Util.php';
  214.     * 
  215.     * // build an attribute string
  216.     * $att = array(
  217.     *              "foo"   =>  "bar",
  218.     *              "argh"  =>  "tomato"
  219.     *            );
  220.     *
  221.     * $attList = XML_Util::attributesToString($att);    
  222.     * </code>
  223.     *
  224.     * @access   public
  225.     * @static
  226.     * @param    array         $attributes        attribute array
  227.     * @param    boolean|array $sort              sort attribute list alphabetically, may also be an assoc array containing the keys 'sort', 'multiline', 'indent', 'linebreak' and 'entities'
  228.     * @param    boolean       $multiline         use linebreaks, if more than one attribute is given
  229.     * @param    string        $indent            string used for indentation of multiline attributes
  230.     * @param    string        $linebreak         string used for linebreaks of multiline attributes
  231.     * @param    integer       $entities          setting for entities in attribute values (one of XML_UTIL_ENTITIES_NONE, XML_UTIL_ENTITIES_XML, XML_UTIL_ENTITIES_XML_REQUIRED, XML_UTIL_ENTITIES_HTML)
  232.     * @return   string                           string representation of the attributes
  233.     * @uses     XML_Util::replaceEntities() to replace XML entities in attribute values
  234.     * @todo     allow sort also to be an options array
  235.     */
  236.     function attributesToString($attributes, $sort = true, $multiline = false, $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML)
  237.     {
  238.         /**
  239.          * second parameter may be an array
  240.          */
  241.         if (is_array($sort)) {
  242.             if (isset($sort['multiline'])) {
  243.                 $multiline = $sort['multiline'];
  244.             }
  245.             if (isset($sort['indent'])) {
  246.                 $indent = $sort['indent'];
  247.             }
  248.             if (isset($sort['linebreak'])) {
  249.                 $multiline = $sort['linebreak'];
  250.             }
  251.             if (isset($sort['entities'])) {
  252.                 $entities = $sort['entities'];
  253.             }
  254.             if (isset($sort['sort'])) {
  255.                 $sort = $sort['sort'];
  256.             } else {
  257.                 $sort = true;
  258.             }
  259.         }
  260.         $string = '';
  261.         if (is_array($attributes) && !empty($attributes)) {
  262.             if ($sort) {
  263.                 ksort($attributes);
  264.             }
  265.             if( !$multiline || count($attributes) == 1) {
  266.                 foreach ($attributes as $key => $value) {
  267.                     if ($entities != XML_UTIL_ENTITIES_NONE) {
  268.                         $value = XML_Util::replaceEntities($value, $entities);
  269.                     }
  270.                     $string .= ' '.$key.'="'.$value.'"';
  271.                 }
  272.             } else {
  273.                 $first = true;
  274.                 foreach ($attributes as $key => $value) {
  275.                     if ($entities != XML_UTIL_ENTITIES_NONE) {
  276.                         $value = XML_Util::replaceEntities($value, $entities);
  277.                     }
  278.                     if ($first) {
  279.                         $string .= " ".$key.'="'.$value.'"';
  280.                         $first = false;
  281.                     } else {
  282.                         $string .= $linebreak.$indent.$key.'="'.$value.'"';
  283.                     }
  284.                 }
  285.             }
  286.         }
  287.         return $string;
  288.     }
  289.  
  290.    /**
  291.     * create a tag
  292.     *
  293.     * This method will call XML_Util::createTagFromArray(), which
  294.     * is more flexible.
  295.     *
  296.     * <code>
  297.     * require_once 'XML/Util.php';
  298.     * 
  299.     * // create an XML tag:
  300.     * $tag = XML_Util::createTag("myNs:myTag", array("foo" => "bar"), "This is inside the tag", "http://www.w3c.org/myNs#");
  301.     * </code>
  302.     *
  303.     * @access   public
  304.     * @static
  305.     * @param    string  $qname             qualified tagname (including namespace)
  306.     * @param    array   $attributes        array containg attributes
  307.     * @param    mixed   $content
  308.     * @param    string  $namespaceUri      URI of the namespace
  309.     * @param    integer $replaceEntities   whether to replace XML special chars in content, embedd it in a CData section or none of both
  310.     * @param    boolean $multiline         whether to create a multiline tag where each attribute gets written to a single line
  311.     * @param    string  $indent            string used to indent attributes (_auto indents attributes so they start at the same column)
  312.     * @param    string  $linebreak         string used for linebreaks
  313.     * @return   string  $string            XML tag
  314.     * @see      XML_Util::createTagFromArray()
  315.     * @uses     XML_Util::createTagFromArray() to create the tag
  316.     */
  317.     function createTag($qname, $attributes = array(), $content = null, $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES, $multiline = false, $indent = "_auto", $linebreak = "\n")
  318.     {
  319.         $tag = array(
  320.                      "qname"      => $qname,
  321.                      "attributes" => $attributes
  322.                     );
  323.  
  324.         // add tag content
  325.         if ($content !== null) {
  326.             $tag["content"] = $content;
  327.         }
  328.         
  329.         // add namespace Uri
  330.         if ($namespaceUri !== null) {
  331.             $tag["namespaceUri"] = $namespaceUri;
  332.         }
  333.  
  334.         return XML_Util::createTagFromArray($tag, $replaceEntities, $multiline, $indent, $linebreak);
  335.     }
  336.  
  337.    /**
  338.     * create a tag from an array
  339.     * this method awaits an array in the following format
  340.     * <pre>
  341.     * array(
  342.     *  "qname"        => $qname         // qualified name of the tag
  343.     *  "namespace"    => $namespace     // namespace prefix (optional, if qname is specified or no namespace)
  344.     *  "localpart"    => $localpart,    // local part of the tagname (optional, if qname is specified)
  345.     *  "attributes"   => array(),       // array containing all attributes (optional)
  346.     *  "content"      => $content,      // tag content (optional)
  347.     *  "namespaceUri" => $namespaceUri  // namespaceUri for the given namespace (optional)
  348.     *   )
  349.     * </pre>
  350.     *
  351.     * <code>
  352.     * require_once 'XML/Util.php';
  353.     * 
  354.     * $tag = array(
  355.     *           "qname"        => "foo:bar",
  356.     *           "namespaceUri" => "http://foo.com",
  357.     *           "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
  358.     *           "content"      => "I'm inside the tag",
  359.     *            );
  360.     * // creating a tag with qualified name and namespaceUri
  361.     * $string = XML_Util::createTagFromArray($tag);
  362.     * </code>
  363.     *
  364.     * @access   public
  365.     * @static
  366.     * @param    array   $tag               tag definition
  367.     * @param    integer $replaceEntities   whether to replace XML special chars in content, embedd it in a CData section or none of both
  368.     * @param    boolean $multiline         whether to create a multiline tag where each attribute gets written to a single line
  369.     * @param    string  $indent            string used to indent attributes (_auto indents attributes so they start at the same column)
  370.     * @param    string  $linebreak         string used for linebreaks
  371.     * @return   string  $string            XML tag
  372.     * @see      XML_Util::createTag()
  373.     * @uses     XML_Util::attributesToString() to serialize the attributes of the tag
  374.     * @uses     XML_Util::splitQualifiedName() to get local part and namespace of a qualified name
  375.     */
  376.     function createTagFromArray($tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES, $multiline = false, $indent = "_auto", $linebreak = "\n" )
  377.     {
  378.         if (isset($tag["content"]) && !is_scalar($tag["content"])) {
  379.             return XML_Util::raiseError( "Supplied non-scalar value as tag content", XML_UTIL_ERROR_NON_SCALAR_CONTENT );
  380.         }
  381.  
  382.         if (!isset($tag['qname']) && !isset($tag['localPart'])) {
  383.             return XML_Util::raiseError( 'You must either supply a qualified name (qname) or local tag name (localPart).', XML_UTIL_ERROR_NO_TAG_NAME );
  384.         }
  385.  
  386.         // if no attributes hav been set, use empty attributes
  387.         if (!isset($tag["attributes"]) || !is_array($tag["attributes"])) {
  388.             $tag["attributes"] = array();
  389.         }
  390.         
  391.         // qualified name is not given
  392.         if (!isset($tag["qname"])) {
  393.             // check for namespace
  394.             if (isset($tag["namespace"]) && !empty($tag["namespace"])) {
  395.                 $tag["qname"] = $tag["namespace"].":".$tag["localPart"];
  396.             } else {
  397.                 $tag["qname"] = $tag["localPart"];
  398.             }
  399.         // namespace URI is set, but no namespace
  400.         } elseif (isset($tag["namespaceUri"]) && !isset($tag["namespace"])) {
  401.             $parts = XML_Util::splitQualifiedName($tag["qname"]);
  402.             $tag["localPart"] = $parts["localPart"];
  403.             if (isset($parts["namespace"])) {
  404.                 $tag["namespace"] = $parts["namespace"];
  405.             }
  406.         }
  407.  
  408.         if (isset($tag["namespaceUri"]) && !empty($tag["namespaceUri"])) {
  409.             // is a namespace given
  410.             if (isset($tag["namespace"]) && !empty($tag["namespace"])) {
  411.                 $tag["attributes"]["xmlns:".$tag["namespace"]] = $tag["namespaceUri"];
  412.             } else {
  413.                 // define this Uri as the default namespace
  414.                 $tag["attributes"]["xmlns"] = $tag["namespaceUri"];
  415.             }
  416.         }
  417.  
  418.         // check for multiline attributes
  419.         if ($multiline === true) {
  420.             if ($indent === "_auto") {
  421.                 $indent = str_repeat(" ", (strlen($tag["qname"])+2));
  422.             }
  423.         }
  424.         
  425.         // create attribute list
  426.         $attList    =   XML_Util::attributesToString($tag["attributes"], true, $multiline, $indent, $linebreak );
  427.         if (!isset($tag["content"]) || (string)$tag["content"] == '') {
  428.             $tag    =   sprintf("<%s%s />", $tag["qname"], $attList);
  429.         } else {
  430.             if ($replaceEntities == XML_UTIL_REPLACE_ENTITIES) {
  431.                 $tag["content"] = XML_Util::replaceEntities($tag["content"]);
  432.             } elseif ($replaceEntities == XML_UTIL_CDATA_SECTION) {
  433.                 $tag["content"] = XML_Util::createCDataSection($tag["content"]);
  434.             }
  435.             $tag    =   sprintf("<%s%s>%s</%s>", $tag["qname"], $attList, $tag["content"], $tag["qname"] );
  436.         }        
  437.         return  $tag;
  438.     }
  439.  
  440.    /**
  441.     * create a start element
  442.     *
  443.     * <code>
  444.     * require_once 'XML/Util.php';
  445.     * 
  446.     * // create an XML start element:
  447.     * $tag = XML_Util::createStartElement("myNs:myTag", array("foo" => "bar") ,"http://www.w3c.org/myNs#");
  448.     * </code>
  449.     *
  450.     * @access   public
  451.     * @static
  452.     * @param    string  $qname             qualified tagname (including namespace)
  453.     * @param    array   $attributes        array containg attributes
  454.     * @param    string  $namespaceUri      URI of the namespace
  455.     * @param    boolean $multiline         whether to create a multiline tag where each attribute gets written to a single line
  456.     * @param    string  $indent            string used to indent attributes (_auto indents attributes so they start at the same column)
  457.     * @param    string  $linebreak         string used for linebreaks
  458.     * @return   string  $string            XML start element
  459.     * @see      XML_Util::createEndElement(), XML_Util::createTag()
  460.     */
  461.     function createStartElement($qname, $attributes = array(), $namespaceUri = null, $multiline = false, $indent = '_auto', $linebreak = "\n")
  462.     {
  463.         // if no attributes hav been set, use empty attributes
  464.         if (!isset($attributes) || !is_array($attributes)) {
  465.             $attributes = array();
  466.         }
  467.         
  468.         if ($namespaceUri != null) {
  469.             $parts = XML_Util::splitQualifiedName($qname);
  470.         }
  471.  
  472.         // check for multiline attributes
  473.         if ($multiline === true) {
  474.             if ($indent === "_auto") {
  475.                 $indent = str_repeat(" ", (strlen($qname)+2));
  476.             }
  477.         }
  478.  
  479.         if ($namespaceUri != null) {
  480.             // is a namespace given
  481.             if (isset($parts["namespace"]) && !empty($parts["namespace"])) {
  482.                 $attributes["xmlns:".$parts["namespace"]] = $namespaceUri;
  483.             } else {
  484.                 // define this Uri as the default namespace
  485.                 $attributes["xmlns"] = $namespaceUri;
  486.             }
  487.         }
  488.  
  489.         // create attribute list
  490.         $attList    =   XML_Util::attributesToString($attributes, true, $multiline, $indent, $linebreak);
  491.         $element    =   sprintf("<%s%s>", $qname, $attList);
  492.         return  $element;
  493.     }
  494.  
  495.    /**
  496.     * create an end element
  497.     *
  498.     * <code>
  499.     * require_once 'XML/Util.php';
  500.     * 
  501.     * // create an XML start element:
  502.     * $tag = XML_Util::createEndElement("myNs:myTag");
  503.     * </code>
  504.     *
  505.     * @access   public
  506.     * @static
  507.     * @param    string  $qname             qualified tagname (including namespace)
  508.     * @return   string  $string            XML end element
  509.     * @see      XML_Util::createStartElement(), XML_Util::createTag()
  510.     */
  511.     function createEndElement($qname)
  512.     {
  513.         $element    =   sprintf("</%s>", $qname);
  514.         return  $element;
  515.     }
  516.     
  517.    /**
  518.     * create an XML comment
  519.     *
  520.     * <code>
  521.     * require_once 'XML/Util.php';
  522.     * 
  523.     * // create an XML start element:
  524.     * $tag = XML_Util::createComment("I am a comment");
  525.     * </code>
  526.     *
  527.     * @access   public
  528.     * @static
  529.     * @param    string  $content           content of the comment
  530.     * @return   string  $comment           XML comment
  531.     */
  532.     function createComment($content)
  533.     {
  534.         $comment    =   sprintf("<!-- %s -->", $content);
  535.         return  $comment;
  536.     }
  537.     
  538.    /**
  539.     * create a CData section
  540.     *
  541.     * <code>
  542.     * require_once 'XML/Util.php';
  543.     * 
  544.     * // create a CData section
  545.     * $tag = XML_Util::createCDataSection("I am content.");
  546.     * </code>
  547.     *
  548.     * @access   public
  549.     * @static
  550.     * @param    string  $data              data of the CData section
  551.     * @return   string  $string            CData section with content
  552.     */
  553.     function createCDataSection($data)
  554.     {
  555.         return  sprintf("<![CDATA[%s]]>", $data);
  556.     }
  557.  
  558.    /**
  559.     * split qualified name and return namespace and local part
  560.     *
  561.     * <code>
  562.     * require_once 'XML/Util.php';
  563.     * 
  564.     * // split qualified tag
  565.     * $parts = XML_Util::splitQualifiedName("xslt:stylesheet");
  566.     * </code>
  567.     * the returned array will contain two elements:
  568.     * <pre>
  569.     * array(
  570.     *       "namespace" => "xslt",
  571.     *       "localPart" => "stylesheet"
  572.     *      );
  573.     * </pre>
  574.     *
  575.     * @access public
  576.     * @static
  577.     * @param  string    $qname      qualified tag name
  578.     * @param  string    $defaultNs  default namespace (optional)
  579.     * @return array     $parts      array containing namespace and local part
  580.     */
  581.     function splitQualifiedName($qname, $defaultNs = null)
  582.     {
  583.         if (strstr($qname, ':')) {
  584.             $tmp = explode(":", $qname);
  585.             return array(
  586.                           "namespace" => $tmp[0],
  587.                           "localPart" => $tmp[1]
  588.                         );
  589.         }
  590.         return array(
  591.                       "namespace" => $defaultNs,
  592.                       "localPart" => $qname
  593.                     );
  594.     }
  595.  
  596.    /**
  597.     * check, whether string is valid XML name
  598.     *
  599.     * <p>XML names are used for tagname, attribute names and various
  600.     * other, lesser known entities.</p>
  601.     * <p>An XML name may only consist of alphanumeric characters,
  602.     * dashes, undescores and periods, and has to start with a letter
  603.     * or an underscore.
  604.     * </p>
  605.     *
  606.     * <code>
  607.     * require_once 'XML/Util.php';
  608.     * 
  609.     * // verify tag name
  610.     * $result = XML_Util::isValidName("invalidTag?");
  611.     * if (XML_Util::isError($result)) {
  612.     *    print "Invalid XML name: " . $result->getMessage();
  613.     * }
  614.     * </code>
  615.     *
  616.     * @access  public
  617.     * @static
  618.     * @param   string  $string string that should be checked
  619.     * @return  mixed   $valid  true, if string is a valid XML name, PEAR error otherwise
  620.     * @todo    support for other charsets
  621.     */
  622.     function isValidName($string)
  623.     {
  624.         // check for invalid chars
  625.         if (!preg_match("/^[[:alnum:]_\-.]$/", $string{0})) {
  626.             return XML_Util::raiseError( "XML names may only start with letter or underscore", XML_UTIL_ERROR_INVALID_START );
  627.         }
  628.         
  629.         // check for invalid chars
  630.         if (!preg_match("/^([a-zA-Z_]([a-zA-Z0-9_\-\.]*)?:)?[a-zA-Z_]([a-zA-Z0-9_\-\.]+)?$/", $string)) {
  631.             return XML_Util::raiseError( "XML names may only contain alphanumeric chars, period, hyphen, colon and underscores", XML_UTIL_ERROR_INVALID_CHARS );
  632.          }
  633.         // XML name is valid
  634.         return true;
  635.     }
  636.  
  637.    /**
  638.     * replacement for XML_Util::raiseError
  639.     *
  640.     * Avoids the necessity to always require
  641.     * PEAR.php
  642.     *
  643.     * @access   public
  644.     * @param    string      error message
  645.     * @param    integer     error code
  646.     * @return   object PEAR_Error
  647.     */
  648.     function raiseError($msg, $code)
  649.     {
  650.         require_once 'PEAR.php';
  651.         return PEAR::raiseError($msg, $code);
  652.     }
  653. }
  654. ?>